require'wx'
require'aliengl'

--utils function for wx
ID = wx.wxXmlResource.GetXRCID


------------------------------------------------------------------------
--  case interface
------------------------------------------------------------------------
case = {}
local function resetcase()
    case = {
        info       = nil,
        xrc        = nil,
        desc       = nil,
        ctrls      = nil,
        render     = function (self) end,
        init       = function (self) end,
        onsize     = function (self, event) end,
        mouseup    = function (self, event) end,
        mousedown  = function (self, event) end,
        rmouseup   = function (self, event) end,
        rmousedown = function (self, event) end,
        motion     = function (self, event) end,
    }
end

--load case's xrc and etc...
local function postloadcase()
    
end

function loadcase(o)
    if type(path) == 'table' then
        resetcase()
        for k,v in pairs(o) do
            case[k] = v
        end
    elseif type(path) == 'string' then
        resetcase()
        dofile(path)
    else
        error('loadcase() only take table or string as parameter', 2)
    end
    postloadcase()
end

------------------------------------------------------------------------
--  OpenGL canvas
------------------------------------------------------------------------
local canvas = {}
canvas.__index = canvas
setmetatable(canvas, canvas)
function canvas:__call(parent)
    local o = wx.wxGLCanvas(parent)
    o.ctx = wx.wxGLContext(o)
    o:Connect(wx.wxEVT_PAINT           , function (event) canvas.paint(o   , event) end)
    o:Connect(wx.wxEVT_SIZE            , function (event) canvas.onsize(o  , event) end)
    o:Connect(wx.wxEVT_ERASE_BACKGROUND, function (event) end)
    o:Connect(wx.wxEVT_LEFT_DOWN       , function (event) case.mousedown(o , event) end)
    o:Connect(wx.wxEVT_LEFT_UP         , function (event) case.mouseup(o   , event) end)
    o:Connect(wx.wxEVT_RIGHT_DOWN      , function (event) case.rmousedown(o, event) end)
    o:Connect(wx.wxEVT_RIGHT_UP        , function (event) case.rmouseup(o  , event) end)
    o:Connect(wx.wxEVT_MOTION          , function (event) case.motion(o    , event) end)
    return o
end

function canvas:paint(event)
    local dc = wx.wxPaintDC(self)
    self:SetCurrent(self.ctx)
    case.render(self, event)
    self:SwapBuffers()
    event:Skip()
    dc:delete()
end

function canvas:onsize(event)
    self:SetCurrent(self.ctx)
    local width, height = self:GetClientSizeWH()
    glViewport(0, 0, width, height)
    case.onsize(self, event)
    event:Skip()
end

------------------------------------------------------------------------
--  GLRotor app
------------------------------------------------------------------------
app = {}
function app:main()
    resetcase()
    self.xrc = wx.wxXmlResource('GLRotor.xrc')
    self.xrc:InitAllHandlers()
    local xrc =self.xrc
    self.frame = wx.wxFrame()
    assert(xrc:LoadFrame(self.frame, wx.NULL, 'MainFrame', wx.NULL))
    self.canvas = canvas(self.frame)
    self.frame:GetSizer():Add(self.canvas, 1, wx.wxALL + wx.wxEXPAND)
    self.mgr = wxaui.wxAuiManager()
    self.mgr:SetManagedWindow(self.frame)
    self.mgr:AddPane(self.canvas, wxaui.wxAuiPaneInfo():
                Name('MainPanel'):Caption('MainPanel'):
                CenterPane()
                )
    self.treepanel = wx.wxPanel()
    assert(xrc:LoadPanel(self.treepanel, self.frame, 'TreePanel'))
    self.casetree = self.treepanel:FindWindow(ID'CaseTree'):DynamicCast'wxTreeCtrl'
    self.mgr:AddPane(self.treepanel, wxaui.wxAuiPaneInfo():
                Name'TreePanel':Caption'Cases':
                Left():CloseButton(False):MaximizeButton(True):
                Layer(1)
                )
    self.logpanel = wx.wxPanel()
    assert(xrc:LoadPanel(self.logpanel, self.frame, 'LogPanel'))
    self.mgr:AddPane(self.logpanel, wxaui.wxAuiPaneInfo():
                Name('LogPanel'):Caption('Log'):
                Bottom():CloseButton(False):Layer(0)
                )
    self.logctrl = self.logpanel:FindWindow(ID'LogCtrl'):DynamicCast'wxTextCtrl'
    self.mgr:Update()
    self.frame:Show(true)
end

function print(s)
    app.logctrl:AppendText(s..'\n')
end

app:main()
wx.wxGetApp():MainLoop()
